#ifndef XPM_DOC_MODEL_XPM_TermList_H
#define XPM_DOC_MODEL_XPM_TermList_H
#include <list>
#include <iostream>
#include "model/Term.h"

namespace xpm {
	using namespace std;
	using namespace conex;	

	class TermRange {
	public:
		TermRange():_posInBlock(0), _length(0), _term(0) {}
		TermRange(int posInBlock,wstring text, string iid) : _posInBlock(posInBlock), _length(text.length()), _text(text), _iid(iid), _term(0) {}
		TermRange(int posInBlock,wstring text, conex::Term *term) : _posInBlock(posInBlock), _length(text.length()), _text(text), _term(term), _iid(term->id()->iid()) {}
		int posInBlock() {return _posInBlock; }
		void setPosInBlock(int posInBlock) { _posInBlock = posInBlock; }
		int length() {return _length; }
		int end() { return _posInBlock + _length; }
		string iid() { return _iid; }
		void setIid(string iid) {_iid = iid; }
		wstring text() { return _text; }
		void setText(wstring text) { _text = text; _length = _text.length();}
		conex::Term *term() { return _term; }
		void setTerm(conex::Term * term) { _term = term; }
	private:
		int _posInBlock;
		int _length;
		string _iid;
		wstring _text;
		conex::Term* _term;
	};

	struct SelectionRange {
		int startpos;
		int blockpos;
		wstring text;
		string iid;
	};

	class RemainRange {
	public:
		RemainRange(int position = 0, int length = 0): _position(position), _length(length) {}
		int length() {return _length;}
		int end() {return _position + _length; }
		void setLength(int length) { _length = length; }
		int position() {return _position;}
		void setPosition(int position) { _position = position;}
	private:
		int _position;
		int _length;
	};

	typedef list<TermRange>::iterator TermIter;
	typedef pair<RemainRange, RemainRange> RemainRangePair;

	class XpmTermBlock {
	public:
		XpmTermBlock(int pos):_pos(pos) {}
		~XpmTermBlock() {}
		void clear();
		int position();
		int end();
		int start();
		void setTextBlockPos(int pos);		
		list<TermRange>& GetTerms();
		TermIter GetTermIterByPos(int pos);
		//inferfaces
		void findTermRanges(int pos, int len, vector<TermRange>& trs);
		//void AddSomethingBefore(int charsAdded);
		void AddSomethingBefore(int startpos, int charsAdded);
		RemainRangePair AddCharsInPosRange(int startpos, int charsAdded);
		RemainRangePair AddMap(int startpos, wstring text, conex::Term* term);
		RemainRange RemoveMap(TermIter& termIter);
		void AppendTermRange(int startpos, wstring text, conex::Term* term);
		//void RemoveSomethingBefore(int chardRemoved);
		void RemoveSomethingBefore(int startpos, int charsRemoved);
		RemainRangePair RemoveCharsInPosRange(int startpos, int charsRemoved);
		//precise find three seleciton range
	    //void FindByRange(SelectionRange* range,TermIter &term);
		// int size
		int size();
	private:
		list<TermRange> _terms;
		int _pos;
	};
	inline void XpmTermBlock::clear() {
		_terms.clear();
	}
	inline int XpmTermBlock::size() {
		return _terms.size();
	}
	inline int XpmTermBlock::end() {
		if(_terms.size() > 0) {
			return _pos +  _terms.rbegin()->end();
		}else
			return 0;
	}
	inline int XpmTermBlock::start() {
		if(_terms.size() > 0) {
			return _pos + _terms.begin()->posInBlock();
		}else
			return _pos;
	}
    inline void XpmTermBlock::setTextBlockPos(int pos) {
		_pos = pos;
	}
	/*inline void XpmTermBlock::AddSomethingBefore(int charsAdded) {
		_pos += charsAdded;
	}
	inline void XpmTermBlock::RemoveSomethingBefore(int charsRemoved) {
		_pos -= charsRemoved;
	}*/
	inline int XpmTermBlock::position() {
		return _pos;
	}
	inline list<TermRange>& XpmTermBlock::GetTerms() {
		return _terms;
	}

	typedef list<XpmTermBlock*> TermBlocks;
	typedef TermBlocks::iterator TermBlocksIter;
	typedef TermBlocks::const_iterator TermBlocksConstIter;
}
#endif